WPF

까불이 코더 WPF 유튜브

 

 


 

  1. WPF로 PC카카오톡 로그인 화면을 만들어봐요
  2. C# 강의(24-8. CustomAttribute(사용자정의 어트리뷰트) 실전 활용 예제(Property))

 


 

WPF로 PC카카오톡 로그인 화면을 만들어봐요! [패키지 설치]
https://www.youtube.com/watch?v=eWSP4TOZjj4

 

WPF로 PC카카오톡 로그인 화면을 만들어봐요! [의존성 주입]
https://www.youtube.com/watch?v=DxibckiPDw0&t=316s

 

DesignPattern – Sigleton (싱글톤 패턴) [C#]
https://www.youtube.com/watch?v=GtkglhZkFhE

 


 

 

https://github.com/KaburiCoder/WPF-KabulTalk

 


 

1. WPF로 PC카카오톡 로그인 화면을 만들어봐요! [패키지 설치]

 

Manage Nuget Packages

1. CommunityToolkit.Mvvm 8.2.0 – Microsoft
2. Microsoft.Extensions.DependencyInjection 7.0.0 – Microsoft
3. FontAwesome6.Svg 2.5.1 – Codinion
4. Microsoft.Xaml.Behaviors.Wpf 1.1.39 – Microsoft
5. MySql.Data 8.0.33 – Oracle

 


 

WPF로 PC카카오톡 로그인 화면을 만들어봐요! [의존성 주입]

 

 

.NET Community Toolkit Introduction

 

구글에 검색 : Community toolkit

https://learn.microsoft.com/en-us/dotnet/communitytoolkit/introduction

https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/ioc

 

Dependency Injection -> Inversion of control

의존성 주입 : 객체를 직접 생성하지 않고 서비스에 등록된 것을 불러오면 자동으로 생성해주는 방식

 

 

// App.xaml.cs
// App.xaml 에서 StartupUri="MainWindow.xaml" 부분을 삭제

using Microsoft.Extensions.DependencyInjection;
using MyTalk.Services;
using System;
using System.Windows;

namespace MyTalk
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            Services = ConfigureServices();
            Startup += App_Startup;
        }

        private void App_Startup(object sender, StartupEventArgs e)
        {
            // 생성자에 매개변수를 입력하지 않아도 객체가 만들어짐.
            var mainView = App.Current.Services.GetService<MainWindow>()!;
            mainView.Show();
        }

        public new static App Current => (App)Application.Current;

        public IServiceProvider Services { get; }

        private static IServiceProvider ConfigureServices()
        {
            var services = new ServiceCollection();

            // AddSingleton : 한번 생성이 되면 그 객체는 끝날 때까지 계속 사용            
            // 의존성을 주입하면 생성자에서 불러올 수 있다.
            services.AddSingleton<ITestService, TestService>();
            services.AddSingleton<MainWindow>();
            return services.BuildServiceProvider();
        }
    }
}

 

 

// Services 폴더 생성

------------------------------------------
// ITestService.cs 인터페이스 파일 생성

public interface ITestService
{
    string GetString();
}


------------------------------------------
// TestService.cs 클래스 파일 생성

public class TestService : ITestService
{
    public string GetString()
    {
        return "마이톡입니다.";
    }
}

 

 

public partial class MainWindow : Window
{
    public MainWindow(ITestService testService)
    {
        InitializeComponent();

        MessageBox.Show(testService.GetString());
    }
}

 

 


 

DesignPattern – Sigleton (싱글톤 패턴) [C#]

 

 

싱글톤 패턴

싱글톤 패턴이란, 어떤 클래스가 최초 한 번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴입니다.
이후에는 미리 만들어진 메모리에 있는 인스턴스를 사용하기 때문에 메모리를 절약할 수 있습니다.

 

활용

1. 공통된 객체를 여러 개 생상하면 자원을 낭비할 때
2. 한번 생성한 객체를 여러 곳에서 공유해서 사용해야 할 때
3. 객체 생성에 대한 제한을 두고 싶을 때

 

 

namespace WpfApp1.Singletons
{
    public class Logger
    {
        private readonly StringBuilder _logs = new StringBuilder();

        private Logger() { }

        private static readonly Lazy<Logger> _lazyLogger = new Lazy<Logger>(() => new Logger());
        public static Logger Instance => _lazyLogger.Value;

        public void Log(string message)
        {
            _logs.AppendLine($"{DateTime.Now}: {message}");
        }

        public string GetLogs()
        {
            return _logs.ToString();        }

    }
}

 

 

<StackPanel>
    <Button Click="btnCreateForm2_Click">폼2 생성</Button>
    <Button Click="btnShowLogs_Click">로그 메시지 확인</Button>
</StackPanel>


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Logger.Instance.Log("폼1이 생성되었습니다.");         
    }

    private void btnCreateForm2_Click(object sender, RoutedEventArgs e)
    {
        var frm2 = new Form2();
        frm2.Show();
    }

    private void btnShowLogs_Click(object sender, RoutedEventArgs e)
    {
        string logs = Logger.Instance.GetLogs();
        MessageBox.Show(logs);
    }
}

 

 

 

public partial class Form2 : Window
{
    public Form2()
    {
        InitializeComponent();
        Logger.Instance.Log("폼2가 생성되었습니다.");

        Closed += Form2_Closed;
    }

    private void Form2_Closed(object? sender, EventArgs e)
    {
        Logger.Instance.Log("폼2가 닫혔습니다.");
    }
}

 

 


 

2. C# 강의(24-8. CustomAttribute(사용자정의 어트리뷰트) 실전 활용 예제(Property))

 

https://www.youtube.com/watch?v=MnqJtJV-dLk

 

MainWindow.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        User user = new User()
        {
            Email = "Test@tEsT.Com",
            Name = "CsHarpEXaMpLe",
            Address = "셔울 종로구 세종대로"
        };

        Debug.WriteLine(user);
        Debug.WriteLine("-----");

        user.ApplyAttributes();
        Debug.WriteLine(user);
    }
}

 

 

Models/User.cs

using CustomAttributeExample.Attributes;

namespace CustomAttributeExample.Models
{
    internal class User
    {
        [ToUpper]
        public string Email { get; set; } = "";

        [ToLower]
        public string Name { get; set; } = "";

        [Left(5)]
        public string Address { get; set; } = "";

        public override string? ToString()
        {
            return $"Email: {Email}\nName: {Name}\nAddress: {Address}";
        }
    }
}

 

 

Attributes/AttributeExtensions.cs

using System.Reflection;

namespace CustomAttributeExample.Attributes
{
    internal static class AttributeExtensions
    {
        public static void ApplyAttributes(this object obj)
        {
            var properties = obj.GetType().GetProperties();  // 프로퍼티 가져오기

            foreach (var property in properties)
            {
                var attributes = property.GetCustomAttributes().OfType<ITransformerAttribute<string>>();   //어트리뷰트 가져오기
                foreach (var attr in attributes)
                {
                    string? value = property.GetValue(obj) as string;
                    if (value != null) property.SetValue(obj, attr.Transform(value));
                }
            }
        }
    }
}

 

 

Attributes/ITransformerAttribute.cs

namespace CustomAttributeExample.Attributes
{
    interface ITransformerAttribute<T>
    {
        T Transform(T value);
    }
}

 

 

Attributes/LeftAttribute.cs

namespace CustomAttributeExample.Attributes
{
    [AttributeUsage(AttributeTargets.Property)]
    internal class LeftAttribute : Attribute, ITransformerAttribute<string>
    {
        public LeftAttribute(int length)
        {
            Length = length;
        }

        public int Length { get; }

        public string Transform(string value)
        {
            return value.Length > Length ? value.Substring(0, Length) : value;
        }
    }
}

 

 

Attributes/ToLowerAttribute.cs

namespace CustomAttributeExample.Attributes
{
    [AttributeUsage(AttributeTargets.Property)]
    internal class ToLowerAttribute : Attribute, ITransformerAttribute<string>
    {
        public string Transform(string value)
        {
            return value.ToLower();
        }
    }
}

 

 

Attributes/ToUpperAttribute.cs

namespace CustomAttributeExample.Attributes
{
    [AttributeUsage(AttributeTargets.Property)]
    internal class ToUpperAttribute : Attribute, ITransformerAttribute<string>
    {
        public string Transform(string value)
        {
            return value.ToUpper();
        }
    }
}

 

 

 

 

 

 

 

Related posts

Leave a Comment